#include <ArduinoJson.h>
#include <ArduinoRS485.h>
#include <LT8920.h>
#include "ChiNRF.h"
#include <Base64.h>
#include <retain.h>
const int build=BUILD_NUMBER;
const char *fwname="KM9109_star";
DEFINE_UART_485(Rs4854, 4, -1, -1);
DEFINE_UART_485(Rs4855, 5, -1, -1);

ChiNRF xn297(chip_XN297);
int tmr_8920, tmr_297;
uint8_t buf_8920[64], buf_297[64], len_8920, len_297;
#define LED_WIFI PB1
#define LED_RF PB0
#define LED_485 PB8
#define LED_485_2 PB9
#define LED_232_M PC14
#define LED_232_S PA1
HardwareSerial *curSerial;
int rx_lt8920 = 0, tx_lt8920 = 0;
int rx_xn297 = 0, tx_xn297 = 0;
struct
{
  char channels[8];
  int Serial1_baud, Serial1_config;
  int Serial2_baud, Serial2_config;
  int Serial3_baud, Serial3_config;
  int Serial4_baud, Serial4_config;
  int Serial5_baud, Serial5_config;
  int wt8920, wt297;
  u_int16_t lt8920_channel;
  uint64_t xn297_txaddr, xn297_P0, xn297_P1, xn297_P2, xn297_P3, xn297_P4, xn297_P5;
} retain;
retain_EEPROM rem((uint16 *)&retain, sizeof(retain));
void cbSend8920()
{
  lt8920.sendPacket(buf_8920, len_8920);
  len_8920 = 0;
  tx_lt8920++;
  lt8920.startListening();
}
void cbSend297()
{
  xn297.writeTxPayload(buf_297, len_297);
  len_297 = 0;
}
void load_default()
{
  for (int i = 0; i < 8; i++)
    retain.channels[i] = 0;
  retain.Serial1_baud = 115200;
  retain.Serial1_config = SERIAL_8E1;
  retain.Serial2_baud = 9600;
  retain.Serial2_config = SERIAL_8N1;
  retain.Serial3_baud = 9600;
  retain.Serial3_config = SERIAL_8N1;
  retain.Serial4_baud = 9600;
  retain.Serial4_config = SERIAL_8N1;
  retain.Serial5_baud = 9600;
  retain.Serial5_config = SERIAL_8N1;
  retain.wt297 = 20;
  retain.wt8920 = 20;
  retain.lt8920_channel = 50;
}

void xn297_rxcb()
{
  uint8_t buf[255];
  uint8_t len = xn297.readRegister(0x60);
  xn297.readRxPayload(buf, len);
  StaticJsonDocument<256> doc;
  doc["port"] = 7;
  int encodedLength = Base64.encodedLength(len);
  char encodedString[encodedLength];
  Base64.encode(encodedString, (char *)buf, len);
  doc["bytes"] = encodedString;
  serializeJson(doc, Serial1);
  rx_xn297++;
}

void setup()
{
  Serial3.begin(9600);
  {
    load_default();
  }
  Serial1.begin(retain.Serial1_baud, retain.Serial1_config); //WIFI
  Serial1.setTimeout(10);
  Serial2.begin(retain.Serial2_baud, retain.Serial2_config); //232Master
  Serial2.setTimeout(10);
  Serial3.begin(retain.Serial3_baud, retain.Serial3_config); //232 slave
  Serial3.setTimeout(10);
  Rs4854.begin(retain.Serial4_baud, retain.Serial4_config); //485-1
  Rs4854.setTimeout(10);
  Rs4855.begin(retain.Serial5_baud, retain.Serial5_config); //485-2
  Rs4855.setTimeout(10);

  xn297.setOnReceive(xn297_rxcb);
  xn297.begin(PC5, PA6, PA7, PA5, PA4, PC4);
  lt8920.begin();
  xn297.disguiseAs(chip_XN297);
  xn297.setRxPayloadWidth(0, 1); // pipe0, payloadLen 1

  xn297.setRxAddressP0(retain.xn297_P0);
  xn297.setRxAddressP1(retain.xn297_P1);
  xn297.setRxAddressP2(retain.xn297_P2);
  xn297.setRxAddressP3(retain.xn297_P3);
  xn297.setRxAddressP4(retain.xn297_P4);
  xn297.setRxAddressP5(retain.xn297_P5);
  xn297.setTxAddress(retain.xn297_txaddr);
  if (lt8920.id1 != 0xf413)
  {
    Serial3.println("lt8920 error!!!");
  }
  // lt8920.setCurrentControl(0xf, 0xf);
  lt8920.setDataRate(LT8920::LT8920_62KBPS);
  lt8920.setChannel(retain.lt8920_channel);
  // while (1){
  // //   // Serial3.println("send");
  //   lt8920.sendPacket((uint8_t *)"01234567890123456789", 20);
  // }
  tmr_8920 = 0;

  pinMode(LED_WIFI, OUTPUT);
  pinMode(LED_RF, OUTPUT);
  pinMode(LED_485, OUTPUT);
  pinMode(LED_485_2, OUTPUT);
  pinMode(LED_232_M, OUTPUT);
  pinMode(LED_232_S, OUTPUT);

  // lt8920.setRxCb(lt8920.default_rxcb);
  lt8920.startListening();
}
StaticJsonDocument<256> json;
char buf1[256];
void loop()
{
  static int step = 0;
  char buf[256];
  // if (SerialUSB.isConnected())
  // {
  //   digitalWrite(LED_RF, 1);
  // }
  // if (SerialUSB.isConnected() && (SerialUSB.getDTR() || SerialUSB.getRTS()))
  // {
  //   for (int i = 0; i < 10; i++)
  //   {
  //     SerialUSB.println(123456, BIN);
  //   }
  // }
  if (Serial1.available())
  {
    String c = Serial1.readString();
    DeserializationError error = deserializeJson(json, c);
    if (error)
    {
      Serial.print(F("deserializeJson() failed: "));
      Serial.println(error.c_str());
    }
    else
    {
      int port = json["port"];
      const char *bytes = json["bytes"];
      int decodedLength = Base64.decodedLength((char *)bytes, strlen(bytes));
      char decodedString[decodedLength];
      Base64.decode(decodedString, (char *)bytes, strlen(bytes));
      if (decodedLength)
      {
        switch (port)
        {
        case 2:
          Serial2.write(decodedString, decodedLength);
          break;
        case 3:
          Serial3.write(decodedString, decodedLength);
          break;
        case 4:
          Rs4854.write(decodedString, decodedLength);
          break;
        case 5:
          Rs4855.write(decodedString, decodedLength);
          break;
        case 6:
          lt8920.sendPacket((uint8_t *)decodedString, decodedLength);
          break;
        case 7:
          xn297.writeTxPayload((uint8_t *)decodedString, decodedLength);
          break;
        }
      }
    }
  }
  if (Serial2.available())
  {
    int c = Serial2.readBytes(buf, 256);
    if (c)
    {
      StaticJsonDocument<256> doc;
      doc["port"] = 2;
      int encodedLength = Base64.encodedLength(c);
      char encodedString[encodedLength];
      Base64.encode(encodedString, buf, c);
      doc["bytes"] = encodedString;
      serializeJson(doc, Serial1);
    }
  }
  if (Serial3.available())
  {
    int c = Serial3.readBytes(buf, 256);
    if (c)
    {
      StaticJsonDocument<256> doc;
      doc["port"] = 3;
      int encodedLength = Base64.encodedLength(c);
      char encodedString[encodedLength];
      Base64.encode(encodedString, buf, c);
      doc["bytes"] = encodedString;
      serializeJson(doc, Serial1);
    }
  }
  if (Rs4854.available())
  {
    int c4854 = Rs4854.readBytes(buf, 256);
    if (c4854)
    {
      StaticJsonDocument<256> doc;
      doc["port"] = 4;
      int encodedLength = Base64.encodedLength(c4854);
      char encodedString[encodedLength];
      Base64.encode(encodedString, buf, c4854);
      doc["bytes"] = encodedString;
      serializeJson(doc, Serial1);
    }
  }
  if (Rs4855.available())
  {
    int c4855 = Rs4855.readBytes(buf, 256);
    if (c4855)
    {
      StaticJsonDocument<256> doc;
      doc["port"] = 5;
      int encodedLength = Base64.encodedLength(c4855);
      char encodedString[encodedLength];
      Base64.encode(encodedString, buf, c4855);
      doc["bytes"] = encodedString;
      serializeJson(doc, Serial1);
    }
  }
  if (lt8920.availabled())
  {
    int l = lt8920.readBytes(buf, 255);
    if (l > 0)
    {
      StaticJsonDocument<256> doc;
      doc["port"] = 6;
      int encodedLength = Base64.encodedLength(l);
      if (encodedLength)
      {
        char encodedString[encodedLength];
        Base64.encode(encodedString, (char *)buf, l);
        doc["bytes"] = encodedString;
        serializeJson(doc, Serial1);
      }
    }
  }
  switch (step)
  {
  case 5:
    step = 0;
    break;
  default:
    step++;
  }
  digitalWrite(LED_WIFI, step == 0);
  digitalWrite(LED_RF, step == 1);
  digitalWrite(LED_485, step == 2);
  digitalWrite(LED_485_2, step == 3);
  digitalWrite(LED_232_M, step == 4);
  digitalWrite(LED_232_S, step == 5);
  if (tmr_297 && millis() - tmr_297 > retain.wt297)
  {
    cbSend297();
    tmr_297 = 0;
  }
  if (tmr_8920 && millis() - tmr_8920 > retain.wt8920)
  {
    cbSend8920();
    tmr_8920 = 0;
  }
  rem.loop();
}